<template>
  <div class="base64-tool module-container">
    <div class="module-header">
      <h2>Base64 编解码</h2>
      <p class="module-description">Base64 编码和解码工具，支持文本和文件</p>
    </div>

    <div class="module-content">
      <el-tabs v-model="activeTab">
        <el-tab-pane label="文本编解码" name="text">
          <div class="text-container">
            <div class="input-section">
              <div class="section-header">
                <h3>输入</h3>
                <el-radio-group v-model="textMode" size="small">
                  <el-radio-button label="encode">编码</el-radio-button>
                  <el-radio-button label="decode">解码</el-radio-button>
                </el-radio-group>
              </div>
              <el-input
                type="textarea"
                v-model="textInput"
                :rows="10"
                :placeholder="textMode === 'encode' ? '输入要编码的文本...' : '输入要解码的 Base64 字符串...'"
                @input="processText"
              />
            </div>

            <div class="output-section">
              <div class="section-header">
                <h3>输出</h3>
                <div class="actions">
                  <el-button size="small" @click="copyTextOutput" :disabled="!textOutput">
                    复制
                  </el-button>
                  <el-button size="small" @click="clearText">清空</el-button>
                </div>
              </div>
              <el-input
                type="textarea"
                v-model="textOutput"
                :rows="10"
                placeholder="结果将显示在这里..."
                readonly
              />
            </div>
          </div>
        </el-tab-pane>

        <el-tab-pane label="文件编解码" name="file">
          <div class="file-container">
            <div class="upload-section">
              <el-upload
                class="upload-area"
                drag
                action=""
                :auto-upload="false"
                :on-change="handleFileChange"
                :show-file-list="false"
              >
                <i class="el-icon-upload"></i>
                <div class="el-upload__text">
                  将文件拖到此处，或<em>点击上传</em>
                </div>
                <div class="el-upload__tip" slot="tip">
                  支持任何文件类型，大文件可能需要较长处理时间
                </div>
              </el-upload>

              <div v-if="selectedFile" class="file-info">
                <el-card>
                  <div class="file-details">
                    <i class="el-icon-document"></i>
                    <div>
                      <p class="file-name">{{ selectedFile.name }}</p>
                      <p class="file-size">{{ formatFileSize(selectedFile.size) }}</p>
                    </div>
                  </div>
                  <div class="file-actions">
                    <el-button type="primary" @click="encodeFile">编码为 Base64</el-button>
                    <el-button @click="clearFile">清除</el-button>
                  </div>
                </el-card>
              </div>

              <div v-if="fileBase64" class="result-section">
                <h3>Base64 编码结果</h3>
                <el-input
                  type="textarea"
                  v-model="fileBase64"
                  :rows="10"
                  readonly
                />
                <div class="result-actions">
                  <el-button @click="copyFileBase64">复制</el-button>
                  <el-button @click="downloadAsText">下载为文本</el-button>
                  <el-button @click="decodeFileBase64">解码并下载原文件</el-button>
                </div>
              </div>
            </div>

            <div class="decode-section">
              <h3>或从 Base64 解码文件</h3>
              <el-input
                type="textarea"
                v-model="base64ToFile"
                :rows="5"
                placeholder="粘贴 Base64 字符串以解码为文件..."
              />
              <el-button
                type="primary"
                @click="decodeToFile"
                :disabled="!base64ToFile"
                style="margin-top: 10px"
              >
                解码并下载
              </el-button>
            </div>
          </div>
        </el-tab-pane>

        <el-tab-pane label="URL 安全编码" name="url">
          <div class="url-container">
            <div class="input-section">
              <h3>URL 安全的 Base64 编解码</h3>
              <p class="description">
                URL 安全的 Base64 编码会将 '+' 替换为 '-'，'/' 替换为 '_'，并移除填充字符 '='
              </p>
              <el-input
                type="textarea"
                v-model="urlInput"
                :rows="8"
                placeholder="输入文本或 Base64 字符串..."
              />
              <div class="button-group">
                <el-button type="primary" @click="urlSafeEncode">URL 安全编码</el-button>
                <el-button @click="urlSafeDecode">URL 安全解码</el-button>
              </div>
            </div>

            <div class="output-section">
              <h3>结果</h3>
              <el-input
                type="textarea"
                v-model="urlOutput"
                :rows="8"
                placeholder="结果将显示在这里..."
                readonly
              />
              <el-button @click="copyUrlOutput" :disabled="!urlOutput" style="margin-top: 10px">
                复制结果
              </el-button>
            </div>
          </div>
        </el-tab-pane>
      </el-tabs>
    </div>
  </div>
</template>

<script>
export default {
  name: 'Base64',
  data() {
    return {
      activeTab: 'text',
      textMode: 'encode',
      textInput: '',
      textOutput: '',
      selectedFile: null,
      fileBase64: '',
      base64ToFile: '',
      urlInput: '',
      urlOutput: ''
    }
  },
  methods: {
    processText() {
      if (!this.textInput) {
        this.textOutput = ''
        return
      }

      try {
        if (this.textMode === 'encode') {
          this.textOutput = btoa(unescape(encodeURIComponent(this.textInput)))
        } else {
          this.textOutput = decodeURIComponent(escape(atob(this.textInput)))
        }
      } catch (e) {
        this.textOutput = `错误: ${e.message}`
      }
    },

    copyTextOutput() {
      this.copyToClipboard(this.textOutput)
    },

    clearText() {
      this.textInput = ''
      this.textOutput = ''
    },

    handleFileChange(file) {
      this.selectedFile = file.raw
      this.fileBase64 = ''
    },

    encodeFile() {
      if (!this.selectedFile) return

      const reader = new FileReader()
      reader.onload = (e) => {
        const base64 = e.target.result.split(',')[1]
        this.fileBase64 = base64
      }
      reader.readAsDataURL(this.selectedFile)
    },

    clearFile() {
      this.selectedFile = null
      this.fileBase64 = ''
    },

    copyFileBase64() {
      this.copyToClipboard(this.fileBase64)
    },

    downloadAsText() {
      const blob = new Blob([this.fileBase64], { type: 'text/plain' })
      this.downloadBlob(blob, `${this.selectedFile.name}.base64.txt`)
    },

    decodeFileBase64() {
      if (!this.fileBase64) return
      
      try {
        const byteCharacters = atob(this.fileBase64)
        const byteNumbers = new Array(byteCharacters.length)
        for (let i = 0; i < byteCharacters.length; i++) {
          byteNumbers[i] = byteCharacters.charCodeAt(i)
        }
        const byteArray = new Uint8Array(byteNumbers)
        const blob = new Blob([byteArray], { type: this.selectedFile.type })
        this.downloadBlob(blob, this.selectedFile.name)
      } catch (e) {
        this.$message.error('解码失败: ' + e.message)
      }
    },

    decodeToFile() {
      if (!this.base64ToFile) return

      try {
        const byteCharacters = atob(this.base64ToFile.trim())
        const byteNumbers = new Array(byteCharacters.length)
        for (let i = 0; i < byteCharacters.length; i++) {
          byteNumbers[i] = byteCharacters.charCodeAt(i)
        }
        const byteArray = new Uint8Array(byteNumbers)
        const blob = new Blob([byteArray])
        this.downloadBlob(blob, `decoded_${Date.now()}.bin`)
      } catch (e) {
        this.$message.error('解码失败: ' + e.message)
      }
    },

    urlSafeEncode() {
      if (!this.urlInput) {
        this.urlOutput = ''
        return
      }

      try {
        let base64 = btoa(unescape(encodeURIComponent(this.urlInput)))
        this.urlOutput = base64
          .replace(/\+/g, '-')
          .replace(/\//g, '_')
          .replace(/=/g, '')
      } catch (e) {
        this.urlOutput = `错误: ${e.message}`
      }
    },

    urlSafeDecode() {
      if (!this.urlInput) {
        this.urlOutput = ''
        return
      }

      try {
        let base64 = this.urlInput
          .replace(/-/g, '+')
          .replace(/_/g, '/')
        
        const padding = base64.length % 4
        if (padding) {
          base64 += '='.repeat(4 - padding)
        }
        
        this.urlOutput = decodeURIComponent(escape(atob(base64)))
      } catch (e) {
        this.urlOutput = `错误: ${e.message}`
      }
    },

    copyUrlOutput() {
      this.copyToClipboard(this.urlOutput)
    },

    copyToClipboard(text) {
      navigator.clipboard.writeText(text).then(() => {
        this.$message.success('已复制到剪贴板')
      }).catch(() => {
        this.$message.error('复制失败')
      })
    },

    downloadBlob(blob, filename) {
      const url = URL.createObjectURL(blob)
      const a = document.createElement('a')
      a.href = url
      a.download = filename
      a.click()
      URL.revokeObjectURL(url)
    },

    formatFileSize(bytes) {
      if (bytes < 1024) return bytes + ' B'
      if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(2) + ' KB'
      return (bytes / (1024 * 1024)).toFixed(2) + ' MB'
    }
  }
}
</script>

<style lang="scss" scoped>
@import '../../styles/variables.scss';

.base64-tool {
  .module-content {
    padding: $spacing-large;
  }

  .text-container,
  .url-container {
    display: flex;
    gap: $spacing-large;

    .input-section,
    .output-section {
      flex: 1;

      .section-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: $spacing-base;

        h3 {
          margin: 0;
        }

        .actions {
          display: flex;
          gap: $spacing-small;
        }
      }
    }
  }

  .file-container {
    .upload-area {
      margin-bottom: $spacing-large;
    }

    .file-info {
      margin: $spacing-large 0;

      .file-details {
        display: flex;
        align-items: center;
        gap: $spacing-base;
        margin-bottom: $spacing-base;

        i {
          font-size: 32px;
          color: $primary-color;
        }

        .file-name {
          font-weight: bold;
          margin: 0;
        }

        .file-size {
          color: $text-secondary;
          font-size: $font-size-small;
          margin: 0;
        }
      }

      .file-actions {
        display: flex;
        gap: $spacing-base;
      }
    }

    .result-section {
      margin-top: $spacing-large;

      h3 {
        margin-bottom: $spacing-base;
      }

      .result-actions {
        display: flex;
        gap: $spacing-base;
        margin-top: $spacing-base;
      }
    }

    .decode-section {
      margin-top: $spacing-extra-large;
      padding-top: $spacing-large;
      border-top: 1px solid $border-color;

      h3 {
        margin-bottom: $spacing-base;
      }
    }
  }

  .button-group {
    display: flex;
    gap: $spacing-base;
    margin-top: $spacing-base;
  }

  .description {
    color: $text-secondary;
    font-size: $font-size-small;
    margin: $spacing-base 0;
  }
}
</style>